k8s에서 도커 이미지 구동하기
쿠버네티스에서 도커 이미지를 사용하려면 쿠버네티스가 이미지를 불러올 수 있는 공간에 이미지를 넣어두어야 한다
사전 작업
쿠버네티스는 컨테이너를 효과적으로 다루기 위해서 만들어졌고 컨테이너인 파드도 쉽게 부를 수 있다. 따라서 직접 만든 컨테이너 이미지도 kubectl
명령어로 쿠버네티스 클러스터에서 바로 구동할 수 있다
도커 이미지를 빌드해서 만든 hello:1.0 이미지를 쿠버네티스에서 구동해보자
Dockerfile
FROM openjdk:8 AS int-build
LABEL description="Java Application builder"
WORKDIR /app
RUN git clone https://github.com/iac-source/inbuilder.git
WORKDIR inbuilder
RUN chmod 700 mvnw
RUN ./mvnw clean package
FROM gcr.io/distroless/java:8
LABEL description="Echo IP Java Application"
WORKDIR /opt
COPY /app/inbuilder/target/app-in-host.jar ./app.jar
EXPOSE 80
ENTRYPOINT [ "java", "-jar", "app.jar" ]
이미지 확인
도커 이미지 빌드
$ docker build --tag yshrim12/multistage-img .
도커 이미지 확인
$ docker images yshrim12/multistage-img
REPOSITORY TAG IMAGE ID CREATED SIZE
yshrim12/multistage-img latest 14c516d51db3 15 minutes ago 148MB
도커 이미지 구동
아래 작업을 따라해보자.
1. 위에서 생성한 도커 이미지를 기반으로 디플로이먼트를 생성해보도록 하자. 이때 --image를 옵션으로 줘서 yshrim12/multistage-img를 사용하도록 해보자
$ kubectl create deployment failure1 --image=yshrim12/multistage-img
2. kubectl get pods -w
로 파드의 상태 및 변화를 실시간으로 확인해보자. 상태가 정상이라면 STATUS에 Running이 떠야한다.
$ kubectl get pods -w
NAME READY STATUS RESTARTS AGE
failure1-644b58ccbb-gm6ls 0/1 ErrImagePull 0 14s
failure1-644b58ccbb-gm6ls 0/1 ImagePullBackOff 0 15s
하지만 이미지는 내려받는데 문제가 발생해 ErrImagePull과 ImagePullBackOff라는 오류메시지가 번걸아 표시되고 있다. 이는 이미지가 호스트에도 존재함에도 기본 설정에 따라 이미지를 외부(도커 허브)에서 받아오려고 시도하기 때문이다. 당연히 도커 허브에 저 이미지가 없으니 에러가 발생할 수 밖에 없다.
4. 이번에는 내부에 존재하는 컨테이너 이미지를 사용하도록 설정해 디플로이먼트를 생성해보자. 사용자가 원하는 형태의 디플로이먼트를 만드는 좋은 방법은 현재 수행되는 구문을 YAML 형태로 뽑아내는 것이다. --dry-run
옵션은 해당 내용을 실제로는 적용하지 않은 채 명령을 수행하고, -o yaml
은 현재 수행되는 명령을 YAML 형태로 변환해준다. 두 옵션을 조합하면 현재 수행되는 명령을 YAML 형태로 출력해 사용자가 원하는 형태로 변경이 가능하다.
$ kubectl create deployment failure2 --dry-run=client -o yaml --image=yshrim12/multistage-img > failure2.yaml
마지막에 > failure2.yaml
리다이렉션 기호를 사용하여 실행 결과(출력)를 파일(failure2.yaml)로 저장하였다.
5. failure2.yaml을 열어 컨테이너 설정에 imagePullPolicy: Never 옵션을 다음과 같이 추가해주자. 이 옵션은 외부에서 이미지를 가져오지 않고 호스트에 존재하는 이미지를 사용하게 한다.
spec:
containers:
- image: yshrim12/multistage-img
imagePullPolicy: Never # 추가한 부분
name: multistage-img
resources: {}
status: {}
6. 수정한 failure2.yaml 파일을 디플로이먼트에 적용하고 상태를 확인해보자
$ kubectl apply -f failure2.yaml
NAME READY STATUS RESTARTS AGE
failure2-759bb94cd4-lv95t 0/1 ErrImageNeverPull 0 2s
STATUS가 바뀌었지만 여전히 오류(ErrImageNeverPull)가 발생한다. 내부의 이미지를 사용하도록 옵션도 추가했는데 왜 이미지를 못 가져오는걸까?
7. 기존에 배포한 Deployment들을 모두 삭제하자
$ kubectl delete -f ./failure2.yaml
$ kubectl delete deployment/failure1
8. 워커 노드인 w2-k8s에 접속한 후 Dockerfile을 깃허브에서 받아오자.
$ curl -O https://raw.githubusercontent.com/sysnet4admin/_Book_k8sInfra/main/ch4/4.3.4/Dockerfile
9. 테스트를 위한 컨테이너 이미지를 만들자. Dockerfile의 내용은 #1-dockerfile과 같다.
$ docker build --tag yshrim12/multistage-img .
10. 다시 마스터 노드(m-k8s)로 돌아와 failure2.yaml을 success.yaml로 복사하자
$ cp -R ~/failure2.yaml ~/success.yaml
11. sed 명령어로 success.yaml 파일에 replicas를 1에서 3으로 변경하고 failure2 이름도 success로 변경하자
$ sed -i 's/replicas: 1/replicas: 3/' ./success.yaml
$ sed -i 's/failure2/success1/g' ./success.yaml
<br.
12. 배포 전 w2-k8s 워커 노드에서 도커 이미지가 성공적으로 빌드되었는지 확인하고 이미지가 빌드 되었다면 kubectl apply
로 success.yaml를 실행하고 kubectl get pods -o wide
명령으로 배포에 성공한 노드가 워커 노드 2번(w2-k8s)인지 확인하자
$ kubectl apply -f success.yaml
deployment.apps/success created
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
success-654565dd5-5rrpp 1/1 Running 0 3s 172.16.103.135 w2-k8s <none> <none>
success-654565dd5-pwv5d 1/1 Running 0 3s 172.16.103.136 w2-k8s <none> <none>
success-654565dd5-wm4zt 0/1 ErrImageNeverPull 0 3s 172.16.221.131 w1-k8s <none> <none>
왜 워커 노드 2번(w2-k8s)만 배포에 성공한걸까?. 이유는 컨테이너 이미지가 워커 노드 2번에만 존재하기 때문이다. 워커노드 1번에는 yshrim12/multistage-img 이미지가 없기 때문에 파드를 생성할 수 없다.
마무리
그러면 이걸 어떻게 해결할까?
방법은 크게 두 가지가 존재한다.
기본으로 사용하는 도커 허브에 yshrim12/multistage-img를 올려서 다시 내려받거나
쿠버네티스 클러스터가 접근할 수 있는 곳에 이미지 레지스트리를 만들고 그곳에서 받아오도록 설정하는 것이다.